#ifndef _RDA_LMP_SCO_IMPL_
#define _RDA_LMP_SCO_IMPL_

/***********************************************************************
 *
 * MODULE NAME:    lmp_sco_impl.h
 * PROJECT CODE:   BlueStream
 * DESCRIPTION:    LM device state macros
 * MAINTAINER:     Tom Kerwick
 * DATE:           08 May 2003
 *
 * SOURCE CONTROL: $Id: lmp_config_impl.h,v 1.1 2007/12/19 07:39:30 tianwq Exp $
 *
 * LICENSE:
 *     This source code is copyright (c) 2000-2004 Ceva Inc.
 *     All rights reserved.
 *
 * REVISION HISTORY:
 *    08 May 2003 -   TK       - first version
 *
 *
 ***********************************************************************/

#include "lmp_acl_container.h"
#include "lslc_access.h"

#if (PRAGMA_INLINE==1)
#pragma inline(\
LMscoctr_Get_Air_Coding,\
LMscoctr_Get_Linear_PCM_Bit_Pos,\
LMscoctr_Get_Input_Coding,\
LMscoctr_Get_Input_Data_Format,\
LMscoctr_Get_PCM_Sample_Size,\
LMscoctr_Get_Input_Sample_Size,\
LMscoctr_Get_SCO_Index,\
LMeScoctr_Get_Tx_Packet_Type_in_Slots,\
LMeScoctr_Get_Rx_Packet_Type_in_Slots,\
LMscoctr_GetSlotOccupancy,\
LMeScoctr_Get_Number_eSCO_Connections,\
LMscoctr_Get_Topical_eSCO_Link,\
LMscoctr_Get_Topical_eSCO_Link_Transaction_Type,\
LMscoctr_Set_Topical_eSCO_Link,\
LMscoctr_Find_ACL_Link_From_SCO_Link,\
LMscoctr_Get_eSCO_Scratchpad,\
LMscoctr_Clean_eSCO_Scratchpad,\
LMscoctr_Get_eSCO_Host_Constraints,\
LMscoctr_Suspend_Link,\
LMscoctr_Resume_Link,\
LMscoctr_Store_Topical_Voice_Setting,\
LMscoctr_Restore_Topical_Voice_Setting\
)
#endif



/************************************************************************************
 *
 * FUNCTION: LMscoctr_Get_xxx
 *
 * DESCRIPTION:
 *  Return the part of the voice setting
 *
 ***********************************************************************************/
__INLINE__ t_air_coding_format LMscoctr_Get_Air_Coding(u_int16 voice_setting)
{
    return (t_air_coding_format)((voice_setting) & 0x0003);
}

__INLINE__ u_int8 LMscoctr_Get_Linear_PCM_Bit_Pos(u_int16 voice_setting)
{
    return ((voice_setting >> 2) & 0x0007);
}
__INLINE__ t_input_coding LMscoctr_Get_Input_Coding(u_int16 voice_setting)
{
    if(voice_setting & 0x4000)
        return CVSD_IC;
    else
        return (t_input_coding)((voice_setting >> 8) & 0x0003);
}

__INLINE__ t_input_data_format LMscoctr_Get_Input_Data_Format(u_int16 voice_setting)
{
    return (t_input_data_format)((voice_setting >> 6) & 0x0003);
}

__INLINE__ t_input_sample_size LMscoctr_Get_PCM_Sample_Size(u_int16 voice_setting)
{
    return (t_input_sample_size)((voice_setting >> 5) & 0x0001);
}

__INLINE__ u_int8 LMscoctr_Get_Input_Sample_Size(u_int16 voice_setting)
{
    u_int8 linear_pcm_sample_size = LMscoctr_Get_PCM_Sample_Size(voice_setting);
    if(linear_pcm_sample_size == 1)
        linear_pcm_sample_size = 16;
    else
        linear_pcm_sample_size = 8;
    linear_pcm_sample_size -= LMscoctr_Get_Linear_PCM_Bit_Pos(voice_setting);

    return linear_pcm_sample_size;
}

/***********************************************************************
 * FUNCTION :- LMscoctr_Get_SCO_Index
 *
 * DESCRIPTION :-
 * Returns the SCO index for the SCO link identified by p_sco_link
 ***********************************************************************/
__INLINE__ u_int8 LMscoctr_Get_SCO_Index(const t_sco_info *p_sco_link)
{
    return (p_sco_link->sco_index);
}


#if (PRH_BS_CFG_SYS_LMP_EXTENDED_SCO_SUPPORTED==1)

/***********************************************************************
 * FUNCTION :- LMeScoctr_Get_Tx_Packet_Type_in_Slots
 *
 * DESCRIPTION :-
 * Returns the size (in slots) of the current Slave to Master packet type.
 ***********************************************************************/
__INLINE__ u_int8 LMeScoctr_Get_Tx_Packet_Type_in_Slots(const t_sco_info *p_sco_link)
{
    /*
     * POLL/NULL/EV3: 1 slot
     * EV4/EV5:       3 slots
     */
    if (is_eSCO_Packet_3_Slot(p_sco_link->tx_packet_type))
    {
        return 3;
    }
    else
    {
        return 1;
    }
}


/***********************************************************************
 * FUNCTION :- LMeScoctr_Get_Rx_Packet_Type_in_Slots
 *
 * DESCRIPTION :-
 * Returns the size (in slots) of the current Slave to Master packet type.
 ***********************************************************************/
__INLINE__ u_int8 LMeScoctr_Get_Rx_Packet_Type_in_Slots(const t_sco_info *p_sco_link)
{
    /*
     * POLL/NULL/EV3: 1 slot
     * EV4/EV5:       3 slots
     */
    if (is_eSCO_Packet_3_Slot(p_sco_link->rx_packet_type))
    {
        return 3;
    }
    else
    {
        return 1;
    }
}

/***********************************************************************
 * FUNCTION :- LMscoctr_GetSlotOccupancy
 *
 * Determine the slot occupancy of the specified baseband packet type.
 *
 ***********************************************************************/
__INLINE__ u_int8 LMscoctr_GetSlotOccupancy(t_packet packet_type)
{
    if(is_eSCO_Packet_3_Slot(packet_type))
        return 3;
    return 1;
}


/***********************************************************************
 * FUNCTION :- LMeScoctr_Get_Number_eSCO_Connections
 *
 * DESCRIPTION :-
 * Returns number of eSCOs active
 ***********************************************************************/
__INLINE__ u_int8 LMeScoctr_Get_Number_eSCO_Connections(void)
{
    extern u_int8 _LMeScoctr_number_escos_used;

    return _LMeScoctr_number_escos_used;
}



/***********************************************************************
 * FUNCTION :- LMscoctr_Get_Topical_eSCO_Link()
 *
 * Note: This function only expects one eSCO link to be in the
 * process of being setup/manipulated at any one time.
 *
 * Only two routines should be able to set the
 * "Topical eSCO Link". These are:
 *
 * 1) The incoming LMP_eSCO_link_req handler once the PDU has been
 *    handled to the point where it is definitely a new
 *    LMP transaction that has started.
 * 2) The incoming HCI_Setup_Synchronous_Connection handler
 *    once the PDU has been handled to the point where a new
 *    LMP transaction that has started.
 *
 * I am using the Topical eSCO link to represent the eSCO link
 * which has most recently been brought to the eSCO link
 * handlers attention.
 *
 ***********************************************************************/
__INLINE__ t_sco_info *LMscoctr_Get_Topical_eSCO_Link(void)
{
    extern t_sco_info*  _p_LMscoctr_Topical_eSco_Link;

    return _p_LMscoctr_Topical_eSco_Link;
}


/***********************************************************************
 * FUNCTION :- LMscoctr_Set_Topical_eSCO_Link()
 *
 * Note: This function only expects one eSCO link to be in the
 * process of being setup/manipulated at any one time.
 *
 * Only two routines should be able to set the
 * "Topical eSCO Link". These are:
 *
 * 1) The incoming LMP_eSCO_link_req handler once the PDU has been
 *    handled to the point where it is definitely a new
 *    LMP transaction that has started.
 * 2) The incoming HCI_Setup_Synchronous_Connection handler
 *    once the PDU has been handled to the point where a new
 *    LMP transaction that has started.
 *
 * I am using the Topical eSCO link to represent the eSCO link
 * which has most recently been brought to the eSCO link
 * handlers attention.
 *
 ***********************************************************************/
__INLINE__ void LMscoctr_Set_Topical_eSCO_Link(t_sco_info *p_esco_link, t_esco_transaction_type type)
{
    extern t_sco_info*  _p_LMscoctr_Topical_eSco_Link;
    extern t_esco_transaction_type _LMscoctr_Topical_eSco_Link_Transaction_Type;

    _p_LMscoctr_Topical_eSco_Link = p_esco_link;
    _LMscoctr_Topical_eSco_Link_Transaction_Type = type;
}


/***********************************************************************
 * FUNCTION :- LMscoctr_Get_Topical_eSCO_Link_Transaction_Type()
 *
 * Determine if the topical eSCO link is being created, destroyed,
 * or being changed.
 *
 ***********************************************************************/
__INLINE__ t_esco_transaction_type LMscoctr_Get_Topical_eSCO_Link_Transaction_Type(void)
{
    extern t_esco_transaction_type _LMscoctr_Topical_eSco_Link_Transaction_Type;
    return _LMscoctr_Topical_eSco_Link_Transaction_Type;
}


/***********************************************************************
 * FUNCTION :- LMscoctr_Find_ACL_Link_From_SCO_Link()
 *
 * Determine the LMP ACL link associated with an LMP SCO or eSCO link.
 *
 ***********************************************************************/
__INLINE__ t_lmp_link* LMscoctr_Find_ACL_Link_From_SCO_Link(t_sco_info* p_esco)
{
    return LMaclctr_Find_Device_Index(p_esco->device_index);
}

/***********************************************************************
 * FUNCTION :- LMscoctr_Get_eSCO_Scratchpad
 *
 * Locate the scratchpad being used for negotiating the
 * topical eSCO connection.
 *
 ***********************************************************************/
__INLINE__ t_esco_descr* LMscoctr_Get_eSCO_Scratchpad(void)
{
    extern t_esco_descr LMscoctr_eSCO_Scratchpad;
    return &(LMscoctr_eSCO_Scratchpad);
}

/***********************************************************************
 * FUNCTION :- LMscoctr_Clean_eSCO_Scratchpad
 *
 * Zero the scratchpad for negotiating the topical eSCO connection
 * before use.
 *
 ***********************************************************************/
__INLINE__ void LMscoctr_Clean_eSCO_Scratchpad(void)
{
    extern t_esco_descr LMscoctr_eSCO_Scratchpad;
    hw_memset(&LMscoctr_eSCO_Scratchpad, 0, sizeof(LMscoctr_eSCO_Scratchpad));
}

/***********************************************************************
 * FUNCTION :- LMscoctr_Get_eSCO_Host_Constraints
 *
 * Locate the host constraints from last sync command params.
 *
 ***********************************************************************/
__INLINE__ t_esco_host_constraints * LMscoctr_Get_eSCO_Host_Constraints(void)
{
    extern t_esco_host_constraints LMscoctr_eSCO_Host_Constraints;

    return &LMscoctr_eSCO_Host_Constraints;
}

/***********************************************************************
 * LMscoctr_Suspend_Link.
 *
 * This function suspends an eSCO link for a very short while
 * while the controller derives the list of acceptable LMP parameters
 * when changing a link.
 ***********************************************************************/
__INLINE__ void LMscoctr_Suspend_Link(t_sco_info* p_esco_link)
{
    extern t_lm_sco_states LMscoctr_saved_state;

    LMscoctr_saved_state = p_esco_link->state;
    p_esco_link->state = SCO_UNUSED;
}


/***********************************************************************
 * LMscoctr_Resume_Link.
 *
 * This function resumes an eSCO link after
 * while the controller derives the list of acceptable LMP parameters
 * when changing a link.
 ***********************************************************************/
__INLINE__ void LMscoctr_Resume_Link(t_sco_info* p_esco_link)
{
    extern t_lm_sco_states LMscoctr_saved_state;

    p_esco_link->state = LMscoctr_saved_state;

}
#endif
/*
 * The following routines are used on slave-initiated SCO when
 * the IUT is a slave - it frees and re-allocates the SCO container
 * (losing the voice setting information. Store that voice
 * information in a holding variable.
 */
__INLINE__ void LMscoctr_Store_Topical_Voice_Setting(u_int16 voice_setting)
{
    extern u_int16 _LMscoctr_Topical_Voice_Setting;
    _LMscoctr_Topical_Voice_Setting = voice_setting;
}

__INLINE__ u_int16 LMscoctr_Restore_Topical_Voice_Setting(void)
{
    extern u_int16 _LMscoctr_Topical_Voice_Setting;
    return _LMscoctr_Topical_Voice_Setting;
}

#endif

